#include "GiantSpider.h"
#include "Player.h"
#include "DestroyGameObjectMessage.h"
#include "../SGD Wrappers/SGD_GraphicsManager.h"
#include "GameplayState.h"
#include "Game.h"
#include "Boss.h"
#include "CreatePortalMessage.h"
#include "TileSystem.h"
#include "CreateBulletMessage.h"
#include "Projectile.h"
#include "../SGD Wrappers/SGD_AudioManager.h"
#include "GameplayState.h"

GiantSpider::GiantSpider()
{
	StartAnimation("giantspideridle");
	useGravity = true;

	SetLevel(GameplayState::GetInstance()->GetCurrLevel());
}


void GiantSpider::Update(float elapsedTime)
{
	facing = GameplayState::GetInstance()->GetPlayer()->GetPosition().x < m_ptPosition.x ? -1 : 1;
	dt = elapsedTime;

	Enemy::Update(elapsedTime);
	if (!updating) return;

	float distToPlayer = GameplayState::GetInstance()->GetPlayer()->GetPosition().x - GetPosition().x;

	aiming.x = distToPlayer < 0 ? -1.0f : 1.0f;

	if (!ascending && !descending)
		randSwitch -= elapsedTime;

	spitCooldown -= elapsedTime;
}

void GiantSpider::Render()
{
	if (SGD::InputManager::GetInstance()->IsKeyDown(SGD::Key::F4))
		m_iHealth = 0;

	Boss::Render();
	AnimationSystem::GetInstance()->Render({ GetPosition().x - Game::GetInstance()->GetCameraPos().x, GetPosition().y - Game::GetInstance()->GetCameraPos().y }, animInfo);
}

/*virtual*/ bool GiantSpider::DoAttack()
{
	return ((GameplayState::GetInstance()->GetPlayer()->GetPosition() - m_ptPosition).ComputeLength() < 600.0f);
}

/*virtual*/ void GiantSpider::Attack()
{
	GameplayState *gameplay = GameplayState::GetInstance();
	SGD::Point playerPos = gameplay->GetPlayer()->GetPosition();
	float distToPlayer = (playerPos - m_ptPosition).ComputeLength();
	TileSystem *TS = TileSystem::GetInstance();

	bool playerStunned = (gameplay->GetPlayer()->GetStunTimer() > 0);

	if (randSwitch <= 0.0f && !ascending && !descending)
	{
		randSwitch = (rand() % 8) + 8.0f;
		if (onGround)
			ascending = true;
		else
			descending = true;
	}

	//Control movement
	if (onGround)
	{
		if (playerStunned)//stunned
		{
			MoveTowardsPlayer();
		}
		else // not stunned
		{
			// within 300 of player
			if (distToPlayer < 300)
			{
				m_vtVelocity.x = 0.0f;
				// between 45 and 300 from player
				if (abs(playerPos.x - m_ptPosition.x) > 45.0f)
				{
					// player to the left, move right when between 50% and 75% health
					if (playerPos.x < m_ptPosition.x)
					{
						if (GetHealth() > GetMaxHealth() * .50f && GetHealth() < GetMaxHealth() * .75f)
							MoveRight(150);
						else
							MoveTowardsPlayer();
					}
					// player to right, move left when between 50% and 75% health
					else if (m_ptPosition.x < playerPos.x)
					{
						if (GetHealth() > GetMaxHealth() * .50f && GetHealth() < GetMaxHealth() * .75f)
							MoveLeft(150);
						else
							MoveTowardsPlayer();
					}
				}
				// less than 45 from player
				else
				{
					// stop moving
					m_vtVelocity.x = 0.0f;
					// spit on the player (animation)
					if (animInfo.GetCurrAnimation() != "giantspiderspit")
						StartAnimation("giantspiderspit");
				}

				// last 25% of health, double damage
				if (GetHealth() < GetMaxHealth() * .25f && !rage)
				{
					rage = true;
					SetDamage(GetDamage() * 2);
				}
			}
			// over 300 from player (too far away / already retreated)
			else if (abs(playerPos.x - m_ptPosition.x) > 300)
				MoveTowardsPlayer();

			// constantly attacking (spit at player)
			if (spitCooldown < 0.0f && !ascending && !descending)
			{
				spitCooldown = 3.0f;
				CreateBulletMessage * Msg = new CreateBulletMessage{ this, RotationToPlayer(), false };
				Msg->QueueMessage();
			}
		}
	}
	else // on ceiling
	{
		if (playerStunned)
		{
			descending = true;
		}
		else // not stunned
		{
			// randomly descend
			if (rand() % 50 + 1 < 25 && descendTimer <= 0.0f)
				descendTimer = 5.0f;

			if (descendTimer > 0.0f)
				descendTimer -= dt;

			// spit at the player at a higher rate
			if (spitCooldown < 0.0f && !ascending && !descending)
			{
				spitCooldown = 1.0f;
				CreateBulletMessage * Msg = new CreateBulletMessage{ this, RotationToPlayer(), false };
				Msg->QueueMessage();
			}
		}
	}

	if (ascending)
		Ascend();
	else if (descending)
		Descend();
}

void GiantSpider::Ascend()
{
	GameplayState *gameplay = GameplayState::GetInstance();
	TileSystem *TS = TileSystem::GetInstance();

	if (animInfo.GetCurrAnimation() != "giantspiderascend")
		StartAnimation("giantspiderascend");

	if (TS->CheckCollison(gameplay->GetMapIndex(), { GetRect().left, GetRect().top - 20 })
		|| TS->CheckCollison(gameplay->GetMapIndex(), { GetRect().right, GetRect().top - 20 }))
	{
		ascending = false;
		onGround = false;
		useGravity = false;
		m_vtVelocity.y = 0.0f;
		SetAugment(gameplay->RandomizeAugment());
		return;
	}

	useGravity = false;
	m_vtVelocity = { 0.0f, -250.0f };
}

void GiantSpider::Descend()
{
	GameplayState *gameplay = GameplayState::GetInstance();
	TileSystem *TS = TileSystem::GetInstance();
	if (animInfo.GetCurrAnimation() != "giantspiderascend")
		StartAnimation("giantspiderascend");


	if (TS->CheckCollison(gameplay->GetMapIndex(), { GetRect().left, GetRect().bottom + 20 })
		|| TS->CheckCollison(gameplay->GetMapIndex(), { GetRect().right, GetRect().bottom + 20 }))
	{
		descending = false;
		onGround = true;
		m_vtVelocity.y = 0.0f;
		useGravity = true;

		StartAnimation("giantspideridle");
		SetAugment(gameplay->RandomizeAugment());
		return;
	}

	useGravity = false;
	m_vtVelocity = { 0.0f, 250.0f };
}

void GiantSpider::MoveTowardsPlayer()
{
	GameplayState *gameplay = GameplayState::GetInstance();
	SGD::Point playerPos = gameplay->GetPlayer()->GetPosition();

	//Move towards player
	if (abs(playerPos.x - m_ptPosition.x) > 45.0f)
	{
		if (animInfo.GetCurrAnimation() != "giantspiderwalking")
			StartAnimation("giantspiderwalking");

		if (playerPos.x < m_ptPosition.x)
			MoveLeft();
		else
			MoveRight();
	}
	else
	{
		if (animInfo.GetCurrAnimation() != "giantspiderspit")
			StartAnimation("giantspiderspit");

		gameplay->GetPlayer()->SetStunTimer(0.0f);
		m_vtVelocity.x = 0.0f;
	}
}

/*virtual*/ void GiantSpider::EnterDead()
{
	if (state == State::DEAD) return;
	Enemy::EnterDead();

	CreatePortalMessage* ptr = new CreatePortalMessage(0, GetPosition().x, GetPosition().y);
	ptr->QueueMessage();
	SetPlayerNextLevel();
	Boss::SaveHighScore();
}

/*virtual*/ void GiantSpider::HandleEvent(const SGD::Event* pEvent) /*override*/
{
	if (pEvent->GetEventID() == "TODO")
	{

	}
	else
		MovingObject::HandleEvent(pEvent);
}

void GiantSpider::HandleCollision(GameObject* pOther)
{
	if (pOther->GetType() == MovingObject::OBJ_BULLET)
	{
		// don't shoot yourself
		if (((Projectile *)pOther)->GetOwner() == this) return;

		// call MovingObjects HandleCollision
		MovingObject::HandleCollision(pOther);
		// play hit sfx
		SGD::AudioManager::GetInstance()->PlayAudio(damageAudio);
	}

	CharacterCollision(pOther);
}
